﻿using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Win32;
using System.Data.SQLite;

namespace monitor_server
{
    public class dev_add
    {
        public dev_add()
        {
            take_params = true;
        }
        //public bool dev;                            //true - Измерители, false - анализаторы
        public string name;
        //public string prev_name;
        public string blr;
        public string obl;
        //public string prev_obl;
        public string ip;
        public int type;            //0 - анализаторы, 1 - измерители
        //public int prev_type;
        public bool mod;            //true - редактирование/просмотр параметров объекта
        public bool del;            //true - удаление объекта
        public bool cancel;
        public bool take_params;    //true - взять параметры с головного устройства, false - установить свои параметры
    }

    static class Reg
    {
        /// <summary>
        /// Осуществляет поиск в регистре.
        /// </summary>
        /// <param name="key">Где искать.</param>
        /// <param name="find">Что искать.</param>
        /// <returns></returns>
        static public RegFindValue Find(RegistryKey key, string find)
        {
            if (key == null || string.IsNullOrEmpty(find))
                return null;

            string[] props = key.GetValueNames();
            object value = null;

            if (props.Length != 0)
                foreach (string property in props)
                {
                    if (property.IndexOf(find, StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        return new RegFindValue(key, property, null, RegFindIn.Property);
                    }

                    value = key.GetValue(property, null, RegistryValueOptions.DoNotExpandEnvironmentNames);
                    if (value is string && ((string)value).IndexOf(find, StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        return new RegFindValue(key, property, (string)value, RegFindIn.Value);
                    }
                }

            string[] subkeys = key.GetSubKeyNames();
            RegFindValue retVal = null;

            if (subkeys.Length != 0)
            {
                foreach (string subkey in subkeys)
                {
                    try
                    {
                        retVal = Find(key.OpenSubKey(subkey, RegistryKeyPermissionCheck.ReadSubTree), find);
                    }
                    catch (Exception ex)
                    {
                        // err msg, if need
                    }
                    if (retVal != null)
                    {
                        return retVal;
                    }
                }
            }
            key.Close();
            return null;
        }

        public class RegFindValue
        {
            RegistryKey regKey;
            string mProps;
            string mVal;
            RegFindIn mWhereFound;

            public RegistryKey Key
            { get { return regKey; } }

            public string Property
            { get { return mProps; } }

            public string Value
            { get { return mVal; } }

            public RegFindIn WhereFound
            { get { return mWhereFound; } }

            public RegFindValue(RegistryKey key, string props, string val, RegFindIn where)
            {
                regKey = key;
                mProps = props;
                mVal = val;
                mWhereFound = where;
            }
        }

        public enum RegFindIn
        {
            Property,
            Value
        }
    }

    static class server_work
    {
        public static bool createTables()                   //Создание файлов, необходимых для работы с измерителями
        {
            if (!Directory.Exists(@"resources\maps"))
            {
                Directory.CreateDirectory(@"resources\maps");
                return false;
            }

            if (!File.Exists(@"resources\maps\Brest.ini"))
            {
                string str = "[Измерители]\r\nРТПС Колодищи=192.168.1.104,BLR03,1\r\nРТПС Радошковичи=192.168.1.105,BLR04,0\r\n";
                str += "\r\n[Анализаторы]\r\nРТПС Новоселье=192.168.1.107\r\n";
                File.WriteAllText(@"resources\maps\Brest.ini", str, Encoding.GetEncoding("Windows-1251"));

            }
            if (!File.Exists(@"resources\maps\Vitebsk.ini"))
            {
                string str = "[Анализаторы]\r\n";
                str += "\r\n[Измерители]\r\n";
                File.WriteAllText(@"resources\maps\Vitebsk.ini", str, Encoding.GetEncoding("Windows-1251"));
            }
            if (!File.Exists(@"resources\maps\Gomel.ini"))
            {
                string str = "[Анализаторы]\r\n";
                str += "\r\n[Измерители]\r\n";
                File.WriteAllText(@"resources\maps\Gomel.ini", str, Encoding.GetEncoding("Windows-1251"));
            }
            if (!File.Exists(@"resources\maps\Grodno.ini"))
            {
                string str = "[Анализаторы]\r\n";
                str += "\r\n[Измерители]\r\n";
                File.WriteAllText(@"resources\maps\Grodno.ini", str, Encoding.GetEncoding("Windows-1251"));
            }
            if (!File.Exists(@"resources\maps\Minsk.ini"))
            {
                string str = "[Анализаторы]\r\n";
                str += "\r\n[Измерители]\r\n";
                File.WriteAllText(@"resources\maps\Minsk.ini", str, Encoding.GetEncoding("Windows-1251"));
            }
            if (!File.Exists(@"resources\maps\Mogilev.ini"))
            {
                string str = "[Анализаторы]\r\n";
                str += "\r\n[Измерители]\r\n";
                File.WriteAllText(@"resources\maps\Mogilev.ini", str, Encoding.GetEncoding("Windows-1251"));
            }

            if (!File.Exists(@"resources\mainIzmer.ini"))
            {
                string str = "[Головные измерители в областях]\r\n";
                str += "Брестская=0\r\n";
                str += "Витебская=0\r\n";
                str += "Гомельская=0\r\n";
                str += "Гродненская=0\r\n";
                str += "Минская=0\r\n";
                str += "Могилевская=0\r\n";
                int l1 = str.Length;
                File.WriteAllText(@"resources\mainIzmer.ini", str, Encoding.GetEncoding("Windows-1251"));
            }
            return true;
        }

        public static int AccessGainig (int l, byte[] Log, int p, byte[] pass)       //Предоставление доступа в систему
        {
            //FileStream ag = new FileStream(@"resources\access", FileMode.Open);
            string access = "";
            access = File.ReadAllText(@"resources\access");
            int length = access.Length;
            //l = l ^ 71; p = p ^ 71;
            int xorl = 38;
            int xorp = 51;
            int pos = 0;
            int i = 0;
            string s1 = ";";
            string s2 = ".";
            i = s1[0];
            byte b1 = (byte)i;
            i = s2[0];
            byte b2 = (byte)i;
            string login = "";
            string password = "";
            int[] log_i = new int[l];
            for (i = 0; i < l; i++)
            {
                log_i[i] = (int)Log[i];
                log_i[i] = log_i[i] ^ xorl;
                login += (char)log_i[i];
            }
            log_i = new int[p];
            for (i = 0; i < p; i++)
            {
                log_i[i] = (int)pass[i];
                log_i[i] = log_i[i] ^ xorp;
                password += (char)log_i[i];
            }
            i = 0; pos = 0;
            while (true)
            {
                if ((l ^ 71) != (int)access[i])
                {
                    while (true)
                        if (access.Substring(i, 4) == ";.;;")
                            break;
                        else
                            i++;
                    if (i != length - 4)
                    {
                        pos = i + 4;
                        i = pos;
                    }
                    else
                        return 3;
                }
                else
                {
                    if (login != access.Substring(pos + 1, l))
                    {
                        while (true)
                        {
                            if (access.Substring(i, 4) == ";.;;")
                                break;
                            else
                                i++;
                        }
                        if (i != length - 4)
                        {
                            pos = i + 4;
                            i = pos;
                        }
                        else
                            return 3;
                    }
                    else
                        break;

                }
            }
            pos += l + 1;
            if ((p ^ 71) != (int)access[pos])
                return 3;
            pos++;
            if (access.Substring(pos, p) != password)
                return 3;
            pos += p + 1;
            int[] usad = new int[4];
            int k;
            string str = "";
            for (i = 0; i < 4; i++)
            {
                k = (int)access[pos + i];
                usad[i] = k ^ 73;
                str += char.ConvertFromUtf32(usad[i]);
            }
            switch (str)
            {
                case "admi":
                    return 1;
                case "user":
                    return 2;
            }
            return 3;
        }           //Проверка Логин/Пароль

        public static string DetermineRegion (string ipstr)            //Определение области, из которой пришел запрос на вход в систему
        {
            //Возвращает "false"     - неудачная попытка получить доступ к файлу clients.csv
            //           "not_found" - такого ip-адреса в списке клиентов нет
            string[] read;
            int l = ipstr.Length;
            try
            {
                read = File.ReadAllLines(@"resources\clients.csv", Encoding.GetEncoding("Windows-1251"));
            }
            catch (IOException)
            { return "false"; }
            catch (AccessViolationException)
            { return "false"; }
            catch (UnauthorizedAccessException)
            { return "false"; }
            int len = read.Length - 1;
            while (len > 0)
            {
                string[] ips = read[len].Split(';')[1].Split(',');
                foreach (string ip in ips)
                {
                    if (ip.Trim() == ipstr)
                    {
                        return read[len].Split(';')[0];
                    }
                }
                len--;
            }
            return "not_found";
        }

        public static string Analizators (ref List<Analiz> list)
        {
            createTables();
            list.Clear();
            string dev = "";
            string[] obl = File.ReadAllLines(@"resources\maps\Brest.ini", Encoding.GetEncoding("Windows-1251"));
            for (int j = 0; j < 6; j++)
            {
                while (true)
                {
                    string nameee = "";
                    try
                    {
                        switch (j)
                        {
                            case 0:
                                nameee = "maps\\Brest.ini";
                                obl = File.ReadAllLines(@"resources\maps\Brest.ini", Encoding.GetEncoding("Windows-1251"));
                                break;
                            case 1:
                                nameee = "maps\\Gomel.ini";
                                obl = File.ReadAllLines(@"resources\maps\Gomel.ini", Encoding.GetEncoding("Windows-1251"));
                                break;
                            case 2:
                                nameee = "maps\\Grodno.ini";
                                obl = File.ReadAllLines(@"resources\maps\Grodno.ini", Encoding.GetEncoding("Windows-1251"));
                                break;
                            case 3:
                                nameee = "maps\\Minsk.ini";
                                obl = File.ReadAllLines(@"resources\maps\Minsk.ini", Encoding.GetEncoding("Windows-1251"));
                                break;
                            case 4:
                                nameee = "maps\\Mogilev.ini";
                                obl = File.ReadAllLines(@"resources\maps\Mogilev.ini", Encoding.GetEncoding("Windows-1251"));                                break;
                            case 5:
                                nameee = "maps\\Vitebsk.ini";
                                obl = File.ReadAllLines(@"resources\maps\Vitebsk.ini", Encoding.GetEncoding("Windows-1251"));
                                break;
                        }
                        break;
                    }
                    catch (IOException)
                    {
                        return nameee;
                    }
                }
                int i = 0;
                while (i < obl.Length)
                {
                    switch (obl[i])
                    {
                        case "[Измерители]":
                            dev = "izm";
                            i++;
                            break;
                        case "[Анализаторы]":
                            dev = "anal";
                            i++;
                            break;
                        case "":
                            i++;
                            break;
                        default:
                            if (dev != "anal")
                            {
                                i++;
                                break;
                            }
                            
                            //ws.WriteLine(ipstr + ";" + name + ";" + blr + ";" + oblast + ";" + mainGet);    //Запись строки
                            string name = obl[i].Split('=')[0];
                            string ip = obl[i].Split('=')[1];
                            Analiz an = new Analiz (ip, name);
                            list.Add(an);
                            i++;
                            break;
                    }
                }
            }
            return "";

        }

    }

    static class DBOperations
    {
        /*private static string serverName = "sus27";
        private static string dbLogin = "dev";
        private static string dbPassword = "dev11f";*/
        private static String sConnectionString = "";// = @"Database = mydb; Server = " + serverName + "; User Id = dev; Password = dev11f";
        private static SQLiteConnection MyConnection;
        private static bool isConnected;
        private static string maxIdTable = "CurMaxIDs";
        private static string table = "";
        private static int currMaxId;
        private static int MaxId = 1000000;                   //максимальный размер таблицы

        public static bool IsConnected
        { get { return isConnected; } }

        public static int RetreiveServerName()
        {
            //1 - ОК.
            //2 - Файл не существует.
            //3 - Файл не доступен для чтения.
            //4 - Некорректное сетевое имя для сервера с БД.
            if (!File.Exists(@"resources\DBServerName.txt"))
                return 2;
            try
            {
                //serverName = File.ReadAllText(@"resources\DBServerName.txt");
                //sConnectionString = @"Database = mydb; Server = " + serverName + "; User Id = " + dbLogin + "; Password = " + dbPassword;
                sConnectionString = "Data Source=mydb.db;Version=3;UTF8Encoding=True;";
            }
            catch (UnauthorizedAccessException)
            {
                return 3;
            }
            if (!DBConnect())
                return 4;
            return 1;
        }
        
        /// <summary>
        /// Функция подключения к бд.
        /// </summary>
        /// <returns></returns>
        public static bool DBConnect()
        {
            if (IsConnected)
                return true;
            MyConnection = new SQLiteConnection(sConnectionString);
            try
            {
                MyConnection.Open();
            }
            catch (Exception)
            {
                return false;
            }
            isConnected = true;
            return true;
        }

        /// <summary>
        /// Функция отключения от БД.
        /// </summary>
        public static void CloseConnect()
        {
            if (!IsConnected)
                return;
            MyConnection.Close();
            isConnected = false;
        }

        /// <summary>
        /// Функция чтения из файла и вызова функции вставки.
        /// </summary>
        /// <param name="csvFile">string путь к *.csv файлу, из которого обновлять лог в БД.</param>
        /// <returns></returns>
        public static int UpdateBD_FromCSV(string csvFilePath)
        {
            //Возвращаемые значения:
            //1 - Все ОК
            //2 - Нет доступа к файлу *.csv
            //3 - Нет соединения с БД
            //4 - Возвращается null для curMaxId
            if(!isConnected)
                isConnected = DBConnect();
            if (!isConnected)
                return 3;
            //bool isConnected = DBConnect();
            //if (!isConnected)
            //    return 3;
            string fileName = csvFilePath.Split('\\')[csvFilePath.Split('\\').Length - 1];
            char[] spl = { ';', '.' };
            string rtps = fileName.Split(spl)[0];
            string devType = fileName.Split(spl)[1];
            int id = 0;
            string in_out = "";

            switch (devType)
            {
                case "izmer":
                    id = 1;
                    table = "log_izmer";
                    break;
                case "analiz":
                    id = 2;
                    table = "log_analyze";
                    in_out = fileName.Split(spl)[2];
                    break;
            }
            currMaxId = 0;
            string getMaxId = "select curmaxid from curmaxids where id = " + id.ToString() + ";";
            SQLiteCommand select = new SQLiteCommand(getMaxId, MyConnection);
            int faka = -1;
            try
            {
                faka = select.ExecuteNonQuery();
            }
            catch (SQLiteException e)
            {
                return 3;
            }
            SQLiteDataReader dr = select.ExecuteReader();
            try
            {
                while (dr.Read())
                    currMaxId = dr.GetInt32(0);                             //curMaxID у нас есть
            }
            catch (SQLiteException)
            {
                return 4;
            }
            finally
            {
                dr.Close();
            }

            string[] str;
            try
            {
                str = File.ReadAllLines(csvFilePath, Encoding.GetEncoding("Windows-1251"));
            }
            catch (IOException)
            { return 2; }
            catch (AccessViolationException)
            { return 2; }
            catch (UnauthorizedAccessException)
            { return 2; }

            string[] colNames = new string[1];
            colNames = str[0].Split(new Char[] { ';' });

            string[] split = new string[colNames.Length];
            
            //----------------------------------------------------------------------------------------------------------------------------------------
            
            switch (id)
            {
                case 1:
                    int repdateColNum = 2;
                    foreach (string st in str)
                    {
                        if (currMaxId == MaxId + 1)
                            currMaxId = 1;
                        if (st == "")
                            continue;
                        split = st.Split(new Char[] { ';' });
                        if (split[repdateColNum] == "0")
                            split[repdateColNum] = "1111-11-11 11:11:11";
                        string[] toDaFunc = new string[split.Length + 1];
                        split.CopyTo(toDaFunc, 0);
                        toDaFunc[toDaFunc.Length - 1] = rtps;
                        DaWriteIzmer(toDaFunc);
                    }
                    break;
                case 2:
                    int dateColNum = 2;
                    foreach (string st in str)
                    {
                        split = st.Split(new Char[] { ';' });
                        if (split[0].Contains("No") || split[0].Length == 0)
                            continue;
                        if (currMaxId == MaxId)
                            currMaxId = 1;
                        split[dateColNum] = DateTime.Parse(split[dateColNum]).Year + "."
                                             + DateTime.Parse(split[dateColNum]).Month + "."
                                             + DateTime.Parse(split[dateColNum]).Day + " "
                                             + DateTime.Parse(split[dateColNum]).TimeOfDay;
                        split[dateColNum] = DateTime.Parse(split[dateColNum]).ToString("yyyy-MM-dd HH:mm:ss");
                        string[] toDaFunc = new string[split.Length + 2];
                        split.CopyTo(toDaFunc, 0);
                        toDaFunc[toDaFunc.Length - 1] = rtps;
                        toDaFunc[toDaFunc.Length - 2] = in_out;
                        DaWriteAnalyze(toDaFunc);
                    }
                    break;
            }

            string updateIdCommand = "Update " + maxIdTable + " set curmaxid = " + currMaxId.ToString() + " where id = " + id.ToString() + ";";
            SQLiteCommand update = new SQLiteCommand(updateIdCommand, MyConnection);
            try
            {
                update.ExecuteNonQuery();
            }
            catch (SQLiteException e)
            {
                Console.Write(e.Message);
            }

            CloseConnect();
            return 1;
        }


        /// <summary>
        /// Функция вставки-обновления измерителя
        /// </summary>
        /// <param name="split">string[] массив столбцов для записи в лог</param>
        /// <returns></returns>
        public static int DaWriteIzmer(string[] split)
        {
            //Возвращаемые значения:
            //1 - Все ОК
            //2 - нечего читать
            //3 - невозможно выполнить запрос                                                                  
            int idrtps, count = 0;
            int err_ColNum = 0, errDate_ColNum = 1, errRep_ColNum = 2, rtps_ColNum = 3;
            string splitstr = "'" + split[err_ColNum] + "',"
                            + "'" + split[errDate_ColNum] + "',"
                            + "'" + split[errRep_ColNum] + "'";
            var GetRtpsId = new SQLiteCommand("select idrtps from rtps where RTPS = '" + split[rtps_ColNum] + "';", MyConnection);
            try
            {
                GetRtpsId.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 3;
            }
            SQLiteDataReader RtpsId = GetRtpsId.ExecuteReader();
            try
            {
                RtpsId.Read();
                idrtps = RtpsId.GetInt32(0);
            }
            catch (SQLiteException)
            {
                return 2;
            }
            finally
            {
                RtpsId.Close();
            }

            var exist = new SQLiteCommand("update " + table + " set idrtps = " + idrtps + ", " +
                                                                        "avariya = '" + split[err_ColNum] + "', " +
                                                                        "errdate = '" + split[errDate_ColNum] + "', " +
                                                                        "repdate = '" + split[errRep_ColNum] + "' " +
                                                                    "where (idrtps = " + idrtps + " " +
                                                                    "and avariya = '" + split[err_ColNum] + "' " +
                                                                    "and errdate = '" + split[errDate_ColNum] + "');", MyConnection);
            try
            {
                count = exist.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 3;
            }

            switch (count)
            {
                case 0:
                    int res = 0;
                    try
                    {
                        var upd = new SQLiteCommand("update " + table + " set idrtps = " + idrtps + ", " +
                                                                        "avariya = '" + split[err_ColNum] + "', " +
                                                                        "errdate = '" + split[errDate_ColNum] + "', " +
                                                                        "repdate = '" + split[errRep_ColNum] + "' " +
                                                                        "where iderr = " + currMaxId + ";", MyConnection);
                        try
                        {
                            res = upd.ExecuteNonQuery();
                        }
                        catch (SQLiteException)
                        {
                            return 3;
                        }
                        if (res == 0)
                        {
                            var ins = new SQLiteCommand("insert into " + table + " values (" + (currMaxId) + /*"," + idrtps + */"," + splitstr + "," + idrtps + ");", MyConnection);
                            try
                            {
                                ins.ExecuteNonQuery();
                            }
                            catch (SQLiteException)
                            {
                                return 3;
                            }
                        }
                        currMaxId++;                        
                        break;
                    }
                    catch (SQLiteException)
                    {
                        return 3;
                    }
            }
            return 1;
        }
        
        /// <summary>
        /// Функция выборки сведений измерителей из бд.
        /// </summary>
        /// <param name="select">Строка параметров выборки. Разделитель - ';'. Порядок: Область, BLR, РТПС, тип аварии, 
        /// нач. и кон. время появления аварии, нач. и кон. время устранения аварии.</param>
        /// <returns></returns>
        public static string[] SelectIzmers(string select)
        {
            //err1 - нет соединения
            //err2 - нечего считывать
            //err3 - невозможно выполнить запрос
            table = "log_izmer";
            int i = 0, k;
            string[] exception = new string[1] { "err:1" };
            if (!isConnected)
                return exception;
            string[] Selstring = SubsplitIzmer(select).Split(';');
            for (i = 0; i < Selstring.Length; i++)
                if (Selstring[i] != "")
                    Selstring[i] = " and (" + Selstring[i] + ")";
            var sel = new SQLiteCommand("select oblast,BLR,RTPS,avariya,errdate,repdate "
                                      + "from oblast O,BLR B,rtps R," + table + " L "
                                      + "where R.idrtps=L.idrtps and O.idobl=R.idobl and B.idblr=R.idblr "
                                      + Selstring[0] + " "
                                      + Selstring[1] + " "
                                      + Selstring[2] + " "
                                      + Selstring[3] + " "
                                      + Selstring[4] + " "
                                      /*+ Selstring[5]*/ + ";", MyConnection);
            try
            {
                sel.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:3" };
                return exception;
            }
            var GetCount = new SQLiteCommand("select count(iderr) "
                                           + "from " + table + " L, oblast O,BLR B,rtps R "
                                           + "where R.idrtps=L.idrtps and O.idobl=R.idobl and B.idblr=R.idblr"
                                           + Selstring[0] + ""
                                           + Selstring[1] + ""
                                           + Selstring[2] + ""
                                           + Selstring[3] + ""
                                           + Selstring[4] + ""
                                           /*+ Selstring[5]*/ + ";", MyConnection);
            try
            {
                GetCount.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:3" };
                return exception;
            }
            SQLiteDataReader countReader = GetCount.ExecuteReader();
            int count = 0;
            try
            {
                countReader.Read();
                count = countReader.GetInt32(0);
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:2" };
                return exception;
            }
            finally
            {
                countReader.Close();
            }
            SQLiteDataReader selRead = sel.ExecuteReader();
            string[] str = new string[count];
            try
            {
                i = 0;
                while (selRead.Read())
                {
                    str[i] += selRead.GetString(0);
                    for (k = 1; k < /*Selstring.Length;*/6; k++)
                    {
                        string strng = selRead.GetString(k);
                        DateTime date;
                        //if (selRead.GetString(k) == DateTime.Parse("1111.11.11 11:11:11").ToString())
                        DateTime.TryParse(strng, out date);
                        if (date.Year == 1111)
                            str[i] += ";Не было исправлено";
                        else
                            str[i] += ";" + selRead.GetString(k);
                    }
                    i++;
                }
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:2" };
                return exception;
            }
            finally
            {
                selRead.Close();
            }
            return str;
        }
        /// <summary>
        /// Функция подготовки введенных значений к реализации выборки для измерителя.
        /// </summary>
        private static string SubsplitIzmer(string select)
        {
            int i = 0;
            string Selstring = "";
            string[] split = select.Split(';');
            for (i = 0; i < split.Length; i++)
            {
                string[] Subsplit = split[i].Split(',');
                switch (i)
                {
                    case 0:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "oblast like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 1:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "BLR like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 2:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "RTPS like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 3:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "avariya like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 4:
                        for (int k = 0; k < Subsplit.Length; k++)
                        {
                            Subsplit[k] = Subsplit[k].Trim();
                            try
                            {
                                DateTime date = DateTime.Parse(Subsplit[k]);
                                //Subsplit[k] = "'" + date.Year + "." + date.Month + "." + date.Day + " " + date.TimeOfDay + "'";
                                Subsplit[k] = "'" + date.ToString("yyyy-MM-dd HH:mm:ss") + "'";
                            }
                            catch (FormatException)
                            {
                                goto FinishCase4;
                            }
                        }
                        Selstring += "errdate between ";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " and ";
                        }
                    FinishCase4:
                        break;
                    case 5:
                        for (int k = 0; k < Subsplit.Length; k++)
                        {
                            Subsplit[k] = Subsplit[k].Trim();
                            try
                            {
                                DateTime date = DateTime.Parse(Subsplit[k]);
                                //Subsplit[k] = "'" + date.Year + "." + date.Month + "." + date.Day + " " + date.TimeOfDay + "'";
                                Subsplit[k] = "'" + date.ToString("yyyy-MM-dd HH:mm:ss") + "'";
                            }
                            catch (FormatException)
                            {
                                goto FinishCase5;
                            }
                        }
                        Selstring += "repdate between ";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " and ";
                        }
                    FinishCase5:
                        break;
                }
                if (i != split.Length - 1)
                    Selstring += ";";
            }
            return Selstring;
        }

        /// <summary>
        /// Функция вставки-обновления логов анализатора.
        /// </summary>
        /// <param name="split">Строка, добавляемая в базу.</param>
        /// <returns></returns>
        private static int DaWriteAnalyze(string[] split)
        {
            //Возвращаемые значения:
            //1 - Все ОК
            //2 - нечего читать
            //3 - невозможно выполнить запрос
            int idrtps, count = 0;

            var GetRtpsId = new SQLiteCommand("select idrtps from rtps where RTPS = '" + split[9] + "';", MyConnection);
            try
            {
                GetRtpsId.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 3;
            }
            SQLiteDataReader RtpsId = GetRtpsId.ExecuteReader();
            try
            {
                RtpsId.Read();
                idrtps = RtpsId.GetInt32(0);
            }
            catch (SQLiteException)
            {
                return 2;
            }
            finally
            {
                RtpsId.Close();
            }
            var exist = new SQLiteCommand("update " + table + " set state = '" + split[1] + "', " +
                                                                        "date_time = '" + split[2] + "', " +
                                                                        "class = '" + split[3] + "', " +
                                                                        "event = '" + split[4] + "', " +
                                                                        "detail = '" + split[5] + "', " +
                                                                        "pid = '" + split[6] + "', " +
                                                                        "service = '" + split[7] + "', " +
                                                                        "idrtps = " + idrtps + ", " +
                                                                        "vhod_vihod = '" + split[8] + "' " +
                                                                    "where (state = '" + split[1] + "'" +
                                                                        " and date_time = '" + split[2] + "'" +
                                                                        " and class = '" + split[3] + "'" +
                                                                        " and event = '" + split[4] + "'" +
                                                                        " and detail = '" + split[5] + "'" +
                                                                        " and pid = '" + split[6] + "'" +
                                                                        " and service = '" + split[7] + "'" +
                                                                        " and idrtps = " + idrtps +
                                                                        " and vhod_vihod = '" + split[8] + "');", MyConnection);
            try
            {
                count = exist.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 3;
            }

            string splitstr = "'" + split[1] + "',"
                            + "'" + split[2] + "',"
                            + "'" + split[3] + "',"
                            + "'" + split[4] + "',"
                            + "'" + split[5] + "',"
                            + "'" + split[6] + "',"
                            + "'" + split[7] + "',"
                                  + idrtps + ","
                            + "'" + split[8] + "'";

            switch (count)
            {
                case 0:
                    int res = 0;
                    var upd = new SQLiteCommand("update " + table + " set state = '" + split[1] + "', " +
                                                                        "date_time = '" + split[2] + "', " +
                                                                        "class = '" + split[3] + "', " +
                                                                        "event = '" + split[4] + "', " +
                                                                        "detail = '" + split[5] + "', " +
                                                                        "pid = '" + split[6] + "', " +
                                                                        "service = '" + split[7] + "', " +
                                                                        "idrtps = " + idrtps + ", " +
                                                                        "vhod_vihod = '" + split[8] + "' " +
                                                                        "where idlog = " + currMaxId + ";", MyConnection);
                    try
                    {
                        res = upd.ExecuteNonQuery();
                    }
                    catch (SQLiteException)
                    {
                        return 3;
                    }
                    if (res == 0)
                    {
                        var ins = new SQLiteCommand("insert into " + table + " values (" + currMaxId + "," + splitstr + ");", MyConnection);
                        try
                        {
                            ins.ExecuteNonQuery();
                        }
                        catch (SQLiteException)
                        {
                            return 3;
                        }
                    }
                    currMaxId++;
                    break;
            }
            return 1;
        }

        /// <summary>
        /// Функция выборки сведений анализатора из бд
        /// </summary>
        /// <param name="select">Строка с данными для поиска.</param>
        /// <returns></returns>
        public static string[] SelectAnalyze(string select)
        {
            //err1 - нет соединения
            //err2 - нечего считывать
            //err3 - невозможно выполнить запрос
            int i = 0, k;
            table = "log_analyze";
            string[] exception = new string[1] { "err:1" };
            if (!isConnected)
                return exception;
            string[] Selstring = SubsplitAnalyze(select).Split(';');
            /*for (i = 0; i < Selstring.Length; i++)
                for (i = 0; i < Selstring.Length; i++)
                    if (Selstring[i] == "" && i == 0)
                    {
                        Selstring[1] = " (" + Selstring[1] + ")";
                        i++;
                    }
                    else if (Selstring[i] != "" && i == 0)
                        Selstring[0] = " (" + Selstring[0] + ")";
                    else if (Selstring[i] != "")
                        Selstring[i] = " and (" + Selstring[i] + ")";*/
            for (i = 0; i < Selstring.Length; i++)
                if (Selstring[i] != "")
                    Selstring[i] = " and (" + Selstring[i] + ")";
            var sel = new SQLiteCommand("select oblast,BLR,RTPS,vhod_vihod,state,date_time,class,event,detail,pid,service "
                                      + "from " + table + " L,oblast O,blr B,rtps R "
                                      + "where R.idrtps=L.idrtps and O.idobl=R.idobl and B.idblr=R.idblr "
                                                 + Selstring[0]
                                                 + Selstring[1]
                                                 + Selstring[2]
                                                 + Selstring[3]
                                                 + Selstring[4]
                                                 + Selstring[5]
                                                 /*+ Selstring[6]*/ + ";", MyConnection);
            try
            {
                sel.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:3" };
                return exception;
            }
            var GetCount = new SQLiteCommand("select count(idlog) "
                                           + "from " + table + " L,oblast O,blr B,rtps R "
                                           + "where R.idrtps=L.idrtps and O.idobl=R.idobl and B.idblr=R.idblr "
                                                    + Selstring[0]
                                                    + Selstring[1]
                                                    + Selstring[2]
                                                    + Selstring[3]
                                                    + Selstring[4]
                                                    + Selstring[5]
                                                    /*+ Selstring[6]*/ + ";", MyConnection);
            try
            {
                GetCount.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:3" };
                return exception;
            }
            SQLiteDataReader countReader = GetCount.ExecuteReader();
            int count = 0;
            try
            {
                countReader.Read();
                count = countReader.GetInt32(0);
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:2" };
                return exception;
            }
            finally
            {
                countReader.Close();
            }
            SQLiteDataReader selRead = sel.ExecuteReader();
            string[] str = new string[count];
            try
            {
                i = 0;
                while (selRead.Read())
                {
                    str[i] += selRead.GetString(0);
                    for (k = 1; k < /*Selstring.Length*/11; k++)
                        str[i] += ";" + selRead.GetString(k);
                    i++;
                }
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err:2" };
                return exception;
            }
            finally
            {
                selRead.Close();
            }
            return str;
        }

        /// <summary>
        /// Функция подготовки введенных значений к реализации выборки для анализатора.
        /// </summary>
        /// <param name="select">Строка с данными для поиска.</param>
        /// <returns></returns>
        public static string SubsplitAnalyze(string select)
        {
            int i = 0;
            string Selstring = "";
            string[] split = select.Split(';');
            for (i = 0; i < split.Length; i++)
            {
                string[] Subsplit = split[i].Split(',');
                switch (i)
                {
                    case 0:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "oblast like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    /*case 1:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "BLR like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;*/
                    case 1:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "RTPS like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 2:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "vhod_vihod like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 3:
                        for (int k = 0; k < Subsplit.Length; k++)
                        {
                            Subsplit[k] = Subsplit[k].Trim();
                            try
                            {
                                DateTime date = DateTime.Parse(Subsplit[k]);
                                //Subsplit[k] = "'" + date.Year + "." + date.Month + "." + date.Day + " " + date.TimeOfDay + "'";
                                Subsplit[k] = "'" + date.ToString("yyyy-MM-dd HH:mm:ss") + "'";
                            }
                            catch (FormatException)
                            {
                                goto FinishCase3;
                            }
                        }
                        Selstring += "date_time between ";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " and ";
                        }
                    FinishCase3:
                        break;
                    case 4:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "class like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                    case 5:
                        for (int k = 0; k < Subsplit.Length; k++)
                            Subsplit[k] = "'%" + Subsplit[k].Trim() + "%'";
                        for (int count = 0; count < Subsplit.Length; count++)
                        {
                            Selstring += "event like " + Subsplit[count];
                            if (count != Subsplit.Length - 1)
                                Selstring += " or ";
                        }
                        break;
                }
                if (i != split.Length - 1)
                    Selstring += ";";
            }
            return Selstring;
        }


        public static int EventJournalUpdate(string name, string details, string date1)
        {
            //1 - OK
            //2 - Невозможно выполнить запрос (скорее всего по причине отсутсвия связи с БД)
            //3 - Нет связи с БД
            if (!IsConnected)
                return 3;
            string insString = "'" + name + "'," +
                               "'" + details + "'," +
                               "'" + date1 + "'";
            var ins = new SQLiteCommand("insert into eventjournal(name,details,date1) values (" + insString + ");", MyConnection);
            try
            {
                ins.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 2;
            }
            return 1;
        }

        public static int EventJournalUpdate(string name, string details, string date1, string date2)
        {
            //1 - OK
            //2 - Невозможно выполнить запрос (скорее всего по причине отсутсвия связи с БД)
            //3 - Отсутствует строка для обновления
            //4 - Нет связи с БД
            int count = 0;
            if (!IsConnected)
                return 4;
            var upd = new SQLiteCommand("update eventjournal " +
                                       "set date2 = '" + date2 + "' " +
                                       "where name = '" + name + "' " +
                                         "and details = '" + details + "' " +
                                         "and date1 = '" + date1 + "';", MyConnection);
            try
            {
                count = upd.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                return 2;
            }
            catch (NullReferenceException)
            { }
            if (count == 0)
                return 3;
            return 1;
        }

        public static string[] EventJournalSelect()
        {
            //err1 - нет соединения
            //err2 - нечего считывать
            //err3 - невозможно выполнить запрос
            int i = 0;
            string[] exception = new string[1] { "err1" };
            if (!isConnected)
                return exception;
            var select = new SQLiteCommand("select * from eventjournal;", MyConnection);
            try
            {
                select.ExecuteNonQuery();
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err3" };
                return exception;
            }
            SQLiteDataReader selReader = select.ExecuteReader();
            List<string> list_str = new List<string>();
            //
            string st = "";
            try
            {
                i = 0;
                while (selReader.Read())
                {
                    st = selReader.GetString(1);
                    for (int k = 2; k < 5; k++)
                    {
                        try
                        {
                            st += ";" + selReader.GetString(k);
                        }
                        catch (Exception)
                        {
                            st += ";";
                        }
                    }
                        //st += ";" + selReader.GetValue(k).ToString();
                    list_str.Add(st);
                    i++;
                }
            }
            catch (SQLiteException)
            {
                exception = new string[1] { "err2" };
                return exception;
            }
            finally
            {
                selReader.Close();
            }
            string[] str = new string[i];
            i = 0;
            foreach (string stp in list_str)
            {
                str[i] = stp;
                i++;
            }
            return str;
        }
    }

    static class curDir
    {
        static string dir;
        public static string curDirectory
        {
            get
            {
                return dir;
            }
            set
            {
                dir = value;
            }
        }
    }

    static class Izmers
    {
        public delegate void getParamsCallback(byte[] returning);

        private static event getParamsCallback getComplete;

        private static int interval = 1000;         //Время ожидания любых ответов с измерителей
        public static int Interval
        {
            get { return interval; }
            set { interval = value * 1000; }
        }

        private static int st_port = 25001;         //Порт, с которого начинается поиск неиспульзуемого порта
        public static int Port
        {
            get { return st_port; }
            set { st_port = value; }
        }

        

        public static string createIzmersList()                      //Создание списка всех активных измерителей и запись в файл izmers.csv
        {
            //Возвращает имя файла, который используется другим процессом или пустую строку "".
            server_work.createTables();
            string dir = curDir.curDirectory; 
            Directory.SetCurrentDirectory(dir);
            string oblast = "";
            string[] obl;
            int i = 0;
            int u = 0, u1;
            string dev = "";
            string name = "";
            string ipstr = "";
            string blr = "";
            char mainGet;               //Указывает необходимость использования параметров головного измерителя
            StreamWriter ws;
            try
            {
                ws = new StreamWriter(@"resources\izmers.csv", false, Encoding.GetEncoding("Windows-1251"));
            }
            catch (IOException)
            {
                return "izmers.csv";
            }
            ws.WriteLine("");
            obl = File.ReadAllLines(@"resources\maps\Brest.ini", Encoding.GetEncoding("Windows-1251"));
            for (int j = 0; j < 6; j++)
            {
                while (true)
                {
                    string nameee = "";
                    try
                    {                        
                        switch (j)
                        {
                            case 0:
                                nameee = "maps\\Brest.ini";
                                obl = File.ReadAllLines(@"resources\maps\Brest.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Брестская";
                                break;
                            case 1:
                                nameee = "maps\\Gomel.ini";
                                obl = File.ReadAllLines(@"resources\maps\Gomel.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Гомельская";
                                break;
                            case 2:
                                nameee = "maps\\Grodno.ini";
                                obl = File.ReadAllLines(@"resources\maps\Grodno.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Гродненская";
                                break;
                            case 3:
                                nameee = "maps\\Minsk.ini";
                                obl = File.ReadAllLines(@"resources\maps\Minsk.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Минская";
                                break;
                            case 4:
                                nameee = "maps\\Mogilev.ini";
                                obl = File.ReadAllLines(@"resources\maps\Mogilev.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Могилевская";
                                break;
                            case 5:
                                nameee = "maps\\Vitebsk.ini";
                                obl = File.ReadAllLines(@"resources\maps\Vitebsk.ini", Encoding.GetEncoding("Windows-1251"));
                                oblast = "Витебская";
                                break;
                        }
                        break;
                    }
                    catch (IOException)
                    {
                        return nameee;
                    }
                }
                i = 0;
                while (i < obl.Length)
                {
                    switch (obl[i])
                    {
                        case "[Измерители]":
                            dev = "izm";
                            i++;
                            break;
                        case "[Анализаторы]":
                            dev = "anal";
                            i++;
                            break;
                        case "":
                            i++;
                            break;
                        default:
                            if (dev != "izm")
                            {
                                i++;
                                break;
                            }
                            u = 0; u1 = 0;
                            while (obl[i][u] != '=')
                                u++;
                            name = obl[i].Substring(0, u);
                            u++;
                            u1 = u;

                            while (obl[i][u1] != ',')
                                u1++;
                            ipstr = obl[i].Substring(u, u1 - u);

                            u1++;
                            while (obl[i].Substring(u, 3) != "BLR")
                                u++;
                            try
                            {
                                blr = obl[i].Substring(u, 5);
                                mainGet = obl[i][u + 6];
                            }
                            catch (ArgumentOutOfRangeException)
                            {
                                blr = obl[i].Substring(u, 4);
                                mainGet = obl[i][u + 5];
                            }

                            ws.WriteLine(ipstr + ";" + name + ";" + blr + ";" + oblast + ";" + mainGet);    //Запись строки
                            u = 1;
                            i++;
                            break;
                    }
                }
            }
            ws.Close();
            return "";
        }

        public static IPAddress[] izmersIps(string obl)                     //Получить массив ip-адресов измерителей в определенной области
        {
            //Возвращает один ip-адрес 0.0.0.0, если в области нет головного измерителя.
            //Возвращает один ip-адрес 1.1.1.1, если файл izmers.csv не существует.
            //Возвращает один ip-адрес 2.2.2.2, если файл izmers.csv используется другим процессом.
            string main = "";
            string[] mIzmers;
            string[] izmers;
            string[] split;
            IPAddress ipm = IPAddress.Parse("0.0.0.0");
            IPAddress[] ret = new IPAddress[1]{IPAddress.Parse("0.0.0.0")};
            int count;
            server_work.createTables();
            mIzmers = File.ReadAllLines(@"resources\mainIzmer.ini", Encoding.GetEncoding("Windows-1251"));
            for (int i = 1; i < mIzmers.Length; i++)
            {
                if (obl == mIzmers[i].Split('=')[0])
                {
                    main = mIzmers[i].Split('=')[1];
                    break;
                }
            }
            if (main == "0")
            {
                return ret;
            }
            count = 0;
            try
            {
                izmers = File.ReadAllLines(@"resources\izmers.csv", Encoding.GetEncoding("Windows-1251"));
            }
            catch (FileNotFoundException)
            {
                ret[0] = IPAddress.Parse("1.1.1.1");
                return ret;
            }
            catch(IOException)
            {
                ret[0] = IPAddress.Parse("2.2.2.2");
                return ret;
            }
            IPAddress[] ips = new IPAddress[izmers.Length];  
            for (int j = 0; j < izmers.Length; j++)
            {
                try
                {
                    split = izmers[j].Split(';');
                    if (split[1] == main)
                    {
                        ipm = IPAddress.Parse(split[0]);
                    }
                    else if (split[3] == obl && split[4] == "1")
                    {
                        ips[count] = IPAddress.Parse(split[0]);
                        count++;
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    continue;
                }
            }
            ret = new IPAddress[count + 1];
            ret[0] = ipm;
            for (int i = 0; i < count; i++)
            {
                ret[i + 1] = ips[i];
            }
            return ret;
        }

        public static byte[] getParams(IPAddress ip)                        //Получить текущие параметры измерителя
        {
            //Возвращаемые параметры:
            //Если не поступило ответа - массив нулей
            //Если есть ответ:
            //0 и 1 байты - Норма (<байт 0>,<байт 1>) 
            //2..8 байты - Эталон (0, <значеие>)
            
            byte[] get = new byte[] { 0x67, 0x65, 0x74 };       //Команда get
            byte[] ret = new byte[9]{0, 0, 0, 0, 0, 0, 0, 0, 0};
            if (ip == IPAddress.Parse("0.0.0.0"))
                return ret;
            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = interval; //таймауты приёма и отправки
            soc.SendTimeout = interval;
            int port = st_port;
            IPEndPoint lpe;
            IPEndPoint ipe = new IPEndPoint(ip, 25001);
            IPAddress lip = IPAddress.Any;
            while (true)
            {
                try
                {
                    lpe = new IPEndPoint(lip, port);
                    soc.Bind(lpe);
                    break;
                }
                catch (SocketException)
                {
                    port++;
                }
            }
            soc.SendTo(get, ipe);
            try
            {
                soc.Receive(ret);
            }
            catch (SocketException)
            {
            }
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
            return ret;
        }

        public static void getParams(IPAddress ip, getParamsCallback callBack)      //Получить текущие параметры измерителя
        {
            //Возвращаемые параметры:
            //Если не поступило ответа - массив нулей
            //Если есть ответ:
            //0 и 1 байты - Норма (<байт 0>,<байт 1>) 
            //2..8 байты - Эталон (0, <значеие>)
            getComplete = callBack;
            byte[] get = new byte[] { 0x67, 0x65, 0x74 };       //Команда get
            byte[] ret = new byte[9] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = interval; //таймауты приёма и отправки
            soc.SendTimeout = interval;
            int port = st_port;
            IPEndPoint lpe;
            IPEndPoint ipe = new IPEndPoint(ip, 25001);
            IPAddress lip = IPAddress.Any;
            try
            {
                lpe = new IPEndPoint(lip, port);
                soc.Bind(lpe);
            }
            catch (SocketException)
            {
                port++;
            }
            soc.SendTo(get, ipe);
            try
            {
                soc.Receive(ret);
            }
            catch (SocketException)
            {
            }
            if (getComplete != null)
                getComplete(ret);
            return;
        }

        public static int checkParams(IPAddress ip, byte[] eq)             //Заменить текущие параметры измерителя на eq, если они другие
        {
            //Возвращаемые значения:
            //1 - Текущие параметры измерителя соотвутствуют проверяемым
            //2 - Новые параметры успешно установлены
            //3 - Неверный размер массива eq
            //4 - Не получено ответа от устройства
            //5 - Неожиданный ответ (При изменении парметров ожидается 'k')            
            byte[] ret = getParams(ip);
            int count = 0;
            for (int i = 0; i < 0; i++)
            {
                if (ret[i] == 0)
                    count++;
            }
            if (count == 9)
                return 4;
            if (eq.Length != ret.Length)
                return 3;
            for (int i = 0; i < ret.Length; i++)
            {
                //if (ret[i] != eq[i])
                if(!ret[i].Equals(eq[i]))
                    return setParams(ip, eq) + 1;
            }
            return 5;
        }

        public static int setParams(IPAddress ip, byte[] set)   //Установка параметров измерителю
        {
            //Возвращаемые значения:
            //1 - Все ОК
            //2 - Неверный размер массива
            //3 - Не получено ответа от устройства
            //4 - Неожиданный ответ (При изменении парметров ожидается 'k')
            //byte[] send = new byte[9];
            byte[] rec = new byte[10];            
            if (set.Length != 9)
                return 2;            
            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = interval; //таймауты приёма и отправки
            soc.SendTimeout = interval;
            int port = st_port;
            IPEndPoint lpe;
            IPEndPoint ipe = new IPEndPoint(ip, 25001);
            IPAddress lip = IPAddress.Any;
            while (true)
            {
                try
                {
                    lpe = new IPEndPoint(lip, port);
                    soc.Bind(lpe);
                    break;
                }
                catch (SocketException)
                {
                    port++;
                }
            }
            soc.SendTo(set, ipe);
            try
            {
                soc.Receive(rec);
            }
            catch (SocketException)
            {
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                return 3;
            }
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
            if (rec[0] != 'k')
                return 4;
            return 1;
        }

        public static int activeObls(out string[] str)          //Создание списка областей, имеющих активные измерители
        {
            //Возвращаемые значения:
            //1 - Все ОК
            //2 - Файл izmers.csv используется другим процессом
            //3 - В системе нет активных устройств
            str = null;
            string[] izmers = new string[1];
            int count = 0;
            string[] obls = new string[6];
            try
            {
                izmers = File.ReadAllLines(@"resources\izmers.csv", Encoding.GetEncoding("Windows-1251"));
            }
            catch(IOException)
            {                
                return 2;                
            }
            int j;
            for (int i = 0; i < izmers.Length; i++)
            {
                try
                {
                    for (j = 0; j < count; j++)
                    {
                        if (obls[j] == izmers[i].Split(';')[3])
                            break;
                    }
                    if (j >= count || count == 0)
                    {
                        obls[count] = izmers[i].Split(';')[3];
                        count++;
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    continue;
                }
            }
            str = new string[count];
            for (int i = 0; i < count; i++)
            {
                str[i] = obls[i];
            }
            if (count == 0)
                return 3;
            return 1;
        }
        
        /// <summary>
        /// Установка головного измерителя в указанной области.
        /// </summary>
        /// <param name="obl">Область.</param>
        /// <param name="newMain">Название РТПС нового измерителя.</param>
        /// <returns></returns>
        public static bool setMainIzmer(string obl, string newMain)         
        {
            //Возвращает false, если нет доступа к файлу mainIzmer.ini или если нет указанной области
            bool done = false;
            string[] split;
            string[] izmers_m;
            StreamWriter sw;
            try
            {
                izmers_m = File.ReadAllLines(@"resources\mainIzmer.ini", Encoding.GetEncoding("Windows-1251"));
                sw = new StreamWriter(@"resources\mainIzmer.ini", false, Encoding.GetEncoding("Windows-1251"));
            }
            catch (IOException)
            { return false; }
            catch (AccessViolationException)
            { return false; }
            catch (UnauthorizedAccessException)
            { return false; }
            for (int i = 0; i < izmers_m.Length; i++)
            {
                split = izmers_m[i].Split('=');
                if (split[0] != obl)
                    sw.WriteLine(izmers_m[i]);
                else
                {
                    if (newMain == "")
                        split[1] = "0";
                    else
                        split[1] = newMain;
                    sw.WriteLine(split[0] + '=' + split[1]);
                    done = true;
                }
            }
            sw.Close();
            if (done)
                return true;
            else
                return false;
        }

        /// <summary>
        /// Создает CSV файлы журналов измерителей.
        /// </summary>
        /// <returns></returns>
        public static bool makeCSV()
        {
            StreamWriter fl;
            if (!Directory.Exists(@"resources\logs\"))
                Directory.CreateDirectory(@"resources\logs\");
            byte[] logs = { 0x6c };
            int i = 0, dcount = 0;
            IPEndPoint ipe, lpe;
            IPAddress ip;
            string name = "", a = "", dateA = "", dateB;
            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = 2000;
            soc.SendTimeout = 2000;
            int p = 0;
            byte[] data = new byte[756];

            while (true)                                                            //поиск не используемого порта
            {
                try
                {
                    lpe = new IPEndPoint(IPAddress.Any, 25000 - p);
                    soc.Bind(lpe);
                    break;
                }
                catch (SocketException)
                {
                    p++;
                }
            }
            String[] file = new string[1];
            while (true)
            {
                try
                {
                    file = File.ReadAllLines(@"resources\izmers.csv", Encoding.GetEncoding("Windows-1251"));
                    break;
                }
                catch (IOException)
                {
                    return false;
                }
            }
            for (i = 1; i < file.Length; i++)
            {
                data = new byte[756];
                name = file[i].Split(';')[1];
                ip = IPAddress.Parse(file[i].Split(';')[0]);
                ipe = new IPEndPoint(ip, 25001);
                p = 0;
                while (p < 4)                                       //попытка установить связь
                    try
                    {
                        soc.SendTo(logs, ipe);
                        soc.Receive(data);
                        break;
                    }
                    catch (SocketException)
                    { p++; }
                    catch (Exception)
                    { p++; }
                if (p == 4)
                    continue;
                string data_string = Encoding.ASCII.GetString(data);
                fl = new StreamWriter(@"resources\logs\" + name + ";izmer.csv", false, Encoding.Default);
                fl.WriteLine();
                for (dcount = 26; dcount >= 0; dcount--)
                    if (data[28 * dcount] == 0xFF)                                       //Проверка на наличие записи в строке лога устройства
                        continue;
                    else
                    {
                        a = Encoding.ASCII.GetString(data, 28 * dcount, 2);
                        dateA = DateTime.Now.Year.ToString() + "-" +
                            Encoding.ASCII.GetString(data, 28 * dcount + 6, 2) + "-" +      //Месяц
                            Encoding.ASCII.GetString(data, 28 * dcount + 3, 2) + " " +      //День
                            Encoding.ASCII.GetString(data, 28 * dcount + 9, 2) + ":" +      //Часы
                            Encoding.ASCII.GetString(data, 28 * dcount + 12, 2);            //Минуты
                        if (data[28 * dcount + 17] == 255)
                            dateB = "0";
                        else
                        {
                            dateB = DateTime.Now.Year.ToString() + "-" +
                                Encoding.ASCII.GetString(data, 28 * dcount + 14 + 6, 2) + "-" +
                                Encoding.ASCII.GetString(data, 28 * dcount + 14 + 3, 2) + " " +
                                Encoding.ASCII.GetString(data, 28 * dcount + 14 + 9, 2) + ":" +
                                Encoding.ASCII.GetString(data, 28 * dcount + 14 + 12, 2);
                        }
                        fl.WriteLine(a + ';' + dateA + ';' + dateB);
                    }
                fl.Close();
            }
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
            return true;
        }

        public static byte[] getEtalon(IPAddress ip)
        {
            byte[] get = new byte[] { 0x73, 0x74, 0x72, 0x74 };       //Команда get
            byte[] data = new byte[40];
            byte[] ret = new byte[9]; 
            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = interval; //таймауты приёма и отправки
            soc.SendTimeout = interval;
            int port = st_port;
            IPEndPoint lpe;
            IPEndPoint ipe = new IPEndPoint(ip, 25001);
            IPAddress lip = IPAddress.Any;
            try
            {
                lpe = new IPEndPoint(lip, port);
                soc.Bind(lpe);
            }
            catch (SocketException)
            {
                port++;
            }
            
            try
            {
                soc.SendTo(get, ipe);
                soc.Receive(data);
            }
            catch (SocketException)
            {
                return ret;
            }
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
            for (int i = 0; i < 7; i++)
            {
                ret[i] = (byte)((int)data[26 + i] - 48);      //Исправить
            }
            ret[7] = (byte)((int)data[24] - 48);
            ret[8] = (byte)((int)data[25] - 48);
            return ret;
        }
    }

    class Analiz
    {
        private string ip;
        private string name;

        public Analiz(string ip, string name)
        {
            this.ip = ip;
            this.name = name;
        }

        public bool makeCSV()
        {
            string newF = "";
            string type;
            //DirectoryInfo logs = new DirectoryInfo(@"\\" + ip + @"\logs\");
            if (!Directory.Exists(@"\\" + ip + @"\logs\"))
                return false;
            DirectoryInfo logs = new DirectoryInfo(@"\\" + ip + @"\logs\");
            FileInfo[] FI = logs.GetFiles("*.csv");
            int len = logs.GetFiles("*.csv").Length;
            string[] logFiles;
            logFiles = new string[len];
            for (int i = 0; i < len; i++)
                logFiles[i] = FI[i].ToString();
            foreach (string lf in logFiles)
            {
                type = lf.Substring(1, 2).ToString();
                switch (type)
                {
                    case "RF":
                        break;
                    case "AS":
                        type = "ASI";
                        break;
                }
                newF = curDir.curDirectory + @"\resources\logs\" + name + ";analiz;" + type + ".csv";
                if (File.Exists(newF))
                    File.Delete(newF);
                try
                {
                    //string[] str = File.ReadAllLines(logs.ToString() + lf);
                    //System.Windows.Forms.MessageBox.Show("Файл " + logs.ToString() + lf + " считан.");
                    File.Move(logs.ToString() + lf, newF);
                    //File.Delete(logs.ToString() + lf);
                    //System.Windows.Forms.MessageBox.Show("Файл " + logs.ToString() + lf + " удален.");
                    //File.WriteAllLines(newF, str);
                    //System.Windows.Forms.MessageBox.Show("Файл " + newF + " записан.");
                }
                catch (UnauthorizedAccessException)
                {
                    throw new Exception("err:analyzeLogWriteFailed");
                }
                //System.Windows.Forms.MessageBox.Show("1337");
            }
            return true;
        }



    }
}
